#!/usr/bin/perl -w
# -*-perl -*-

# copyright 2004, 2005 k4thryn columbine <k4thryn@krypton.thatbox.net>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
use strict;
use Getopt::Long;

my $version = '0.3.2';

my ($show_help, $show_version, $name, $desc, $dir, $force);

&GetOptions("help"        => \$show_help,
            "version"     => \$show_version,
            "name:s"      => \$name,
            "shortdesc:s" => \$desc,
            "force"       => \$force,
            "dir:s"       => \$dir,
           );

if ( $show_version ) {
  version();
  exit(1);
}
if ( $show_help || !defined($name) ) {
  usage();
  exit(1);
}

$desc = '' if ( ! defined($desc) );

if ( ! defined($dir) ) {
  $dir = './';
}

if ( ! -d $dir ) {
  mkdir($dir) or die "$dir: $!\n";
}

if ( $dir !~ m#/$# ) {
  $dir .= '/';
}

my @date = localtime(time);
my $current_year = $date[5] + 1900;

$_ = <DATA>;
s/%appname%/$name/g;
s/%appdesc%/$desc/g;
/^----(.*)----$/;

my $newfilename = "$dir$1";
if (-e $newfilename && ! $force) {
  print STDERR "$newfilename already exists.  use -f option to overwrite.\n";
  exit(0);
}
print STDERR "writing to $newfilename\n";
open(OUT, "> $newfilename") or die "$newfilename: $!\n";


while(<DATA>) {
  s/%appname%/$name/g;
  s/%appdesc%/$desc/g;
  s/%current_year%/$current_year/g;
  if (/^----(.*)----$/) {
    $newfilename = "$dir$1";
    close(OUT);
    while (-e $newfilename && ! $force) {
      print STDERR "$newfilename already exists.  ",
                   "use -f option to overwrite.\n";
      exit(0);
    }
    print STDERR "writing to $newfilename\n";
    open(OUT, "> $newfilename") or die "$newfilename: $!\n";
  } else {
    print OUT $_;
  }
}

close(OUT);
exit(0);

sub usage {
  print STDERR <<DISCLAIMER;

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
DISCLAIMER

  print STDERR
      "\nnewcapp: makes a few files to get started on a new c application\n",
      "usage: $0 < -h | -n <name> > [-f] [ -s <description> -d <dir>]\n\n";
  print STDERR << 'DONE_OPTS';
  -h, --help             print this message and exit.
  -v, --version          print version number and exit.
  -n, --name <name>      specifies new application name.  (required)
  -s, --shortdesc <desc> description to go in application's usage msg.
                         (default: blank)
  -d, --directory <dir>  place to put the files (default: ./)
  -f, --force            force overwriting files that already exist
DONE_OPTS
}

sub version {
  print STDERR "$0: $version\n";
}

__DATA__
----%appname%.c----
/********************************
  copyright
 ********************************/
#include "%appname%_main.h"

/** @brief  
  * 
  * @param args contains the parsed cmd-line options & arguments.
  * @param argc number of cmd-line arguments.
  * @param argv list of cmd-line arguments
  * @param optind index of the first non-option cmd-line argument.
  * 
  * @return exit status for main() to return.
  */
int %appname% ( struct cmdargs *args, int argc, char *argv[], int optind ) {

  return EXIT_OKAY;
}

----args.tab----
# data relevant to the application as a whole
%global = (
  name          => "%appname%",
  description   => "%appdesc%",
  version       => "0.1",
  trailing_opts => "[file ...]",
  usage_extra   => "",
  do_long_opts  => 1,
  preproc_extra => '',
  copyright     => <<END_COPYRIGHT
copyright %current_year%
END_COPYRIGHT
);

# descriptions of individual command-line arguments
# valid types are
#  flag                - no argument
#  var                 - required argument
#  var_optional        - optional argument
#  custom_flag         - no arg, and specify parseopt_code 
#  custom_var          - required arg, and specify parseopt_code 
#  custom_var_optional - optional arg, and specify parseopt_code 
@args = ( {
    name        => 'help',
    shortopt    => 'h',
    longopt     => 'help',
    type        => 'flag',
    required    => 0,
    main_code   => 'usage(argv[0]); exit(EXIT_HELP);',
    description => 'print this message and exit'
  },
  {
    name        => 'version',
    shortopt    => 'V',
    longopt     => 'version',
    type        => 'flag',
    required    => 0,
    main_code   => 'version(); exit(1);',
    description => 'print version info and exit'
  },
  {
    name          => 'verbose',
    shortopt      => 'v',
    longopt       => 'verbose',
    type          => 'custom_flag',
    required      => 0,
    parseopt_code => 'args->verbose++;',
    description   => 'print verbose messages during execution'
  },
);
----Makefile----
EXECUTABLE := %appname%
DESCRIPTION := %appdesc%
VERSION = 0.1

DISTFILE = $(EXECUTABLE)-$(VERSION).tgz
# resources like README, COPYING, etc., which should be included in
# the distribution file
RESOURCES := 

WORKDIR := $(shell pwd)
CC := $(shell which gcc)

MAINGENERATOR := $(shell which cgener)
ARGSTAB := args.tab
CFLAGS := -O2 -Wall
DBCFLAGS := $(CFLAGS) -g -DDEBUG
LINKFLAGS :=

GEN_FILES := main.c usage.c
GEN_OBJECTS := $(patsubst %.c,%.o,$(GEN_FILES))
CFILES := $(filter-out $(GEN_FILES), $(wildcard *.c))
CHEADERS :=$(wildcard *.h)
OBJECTS := $(patsubst %.c,%.o,$(CFILES))
DEPS := $(patsubst %.o,%.d,$(OBJECTS))

.PHONY : debug deps clean dist

default : $(EXECUTABLE)

deps :  $(OBJECTS) $(GEN_OBJECTS)

debug ::
	$(CC) $(DBCFLAGS) -o $(EXECUTABLE) $(CFILES) $(LINKFLAGS)

clean ::
	rm -f *.o
	rm -f *.d
	rm -f $(GEN_FILES)

dist : $(DISTFILE)

$(DISTFILE) : $(CFILES) $(GEN_FILES) $(CHEADERS) $(RESOURCES)
	@ls $(CFILES) $(GEN_FILES) $(CHEADERS) $(RESOURCES) | sed s:^:$(EXECUTABLE)-$(VERSION)/: >MANIFEST
	@(cd ..; ln -s $(WORKDIR) $(EXECUTABLE)-$(VERSION))
	(cd ..; tar -czvf $(WORKDIR)/$(DISTFILE) `cat $(WORKDIR)/MANIFEST`)
	@(cd ..; rm $(EXECUTABLE)-$(VERSION))

$(GEN_OBJECTS) : $(GEN_FILES)

$(GEN_FILES) : $(ARGSTAB)
	$(MAINGENERATOR) -a $(ARGSTAB)

$(EXECUTABLE) : $(GEN_OBJECTS) $(OBJECTS)
	$(CC) $(CFLAGS) -o $(EXECUTABLE) $(GEN_OBJECTS) $(OBJECTS) $(LINKFLAGS)


